package com.google.bling.client;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;

public class TransactionsChannel {
	static final class Response {
		static final class Transaction {
			protected Transaction(JSONObject json) {
				if (json.containsKey("title")) {
					title = json.get("title").isString().toString();
				}
				if (json.containsKey("total")) {
					total = json.get("total").isNumber().doubleValue();
				}
				if (json.containsKey("payer")) {
					payer = json.get("payer").isString().toString();
				}
				if (json.containsKey("line")) {
					line = new ArrayList<Double>();
					JSONArray json_line = json.get("line").isArray();
					for (int i = 0, I = json_line.size(); i < I; ++i) {
						line.add(json_line.get(i).isNumber().doubleValue());
					}
				}
			}

			public String toString() {
				return "title: " + title +
					"\ntotal: " + total +
					"\npayer: " + payer +
					"\nline: " + line.toString();
			}

			public String title;
			public double total;
			public String payer;
			public List<Double> line;
		}

		protected Response(JSONObject json) {
			JSONArray json_participants = json.get("participants").isArray();
			participants = new ArrayList<String>();
			for (int i = 0, I = json_participants.size(); i < I; ++i) {
				participants.add(Util.removeQuotes(json_participants.get(i).isString().toString()));
			}

			// TODO: Make this use Integers, not doubles (ie: use microcents).
			before = new ArrayList<Double>();
			JSONArray json_before = json.get("before").isArray();
			for (int i = 0, I = json_before.size(); i < I; ++i) {
				before.add(json_before.get(i).isNumber().doubleValue());
			}

			transactions = new ArrayList<Transaction>();
			JSONArray json_transactions = json.get("transactions").isArray();
			for (int i = 0, I = json_transactions.size(); i < I; ++i) {
				transactions.add(new Transaction(json_transactions.get(i).isObject()));
			}

			after = new ArrayList<Double>();
			JSONArray json_after = json.get("after").isArray();
			for (int i = 0, I = json_after.size(); i < I; ++i) {
				after.add(json_after.get(i).isNumber().doubleValue());
			}
		};
		public List<String> participants;
		public List<Double> before;
		public List<Transaction> transactions;
		public List<Double> after;
	}

	static final class WrapperCallback implements JavaScriptObjectCallback {
		public WrapperCallback(TransactionsCallback c) {
			this.c = c;
		}
		public void execute(JavaScriptObject o) {
			this.c.execute(new Response(new JSONObject(o)));
		}
		private TransactionsCallback c;
	}

	public void request(int n, TransactionsCallback c) {
		request_(n, new WrapperCallback(c));
	}

	private native void request_(int n, JavaScriptObjectCallback c)/*-{
    	// NOTE(appleton): Point this at your real AppEngine instance.  For now we mock.
//    	var requestPath = 'http://www.corp.google.com/~appleton/bling/mock_transactions.js';
    	var requestPath = 'http://localhost:8080/group/transactions_list';
    	// HACK(appleton): mock_transactions.js hard-codes this callback name.
    	var callbackName = "myCallbackFunction";

    	// Attach handler to window
    	$wnd[callbackName] = function(o) {
    		c.@com.google.bling.client.JavaScriptObjectCallback::execute(Lcom/google/gwt/core/client/JavaScriptObject;)(o);
  		};

		// Form request url
		var url = requestPath
			+ '?n=' + n
			+ '&id=' + 6
			+ '&callback=' + callbackName;

		// JSONP request
		var script = $doc.createElement('script');
    	script.type = 'text/javascript';
    	script.src = url;
    	$doc.body.appendChild(script);
  	}-*/;
}
